package org.amos.gen.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.amos.core.basic.base.BaseController;
import org.amos.core.basic.constant.SystemConstant;
import org.amos.core.basic.enums.JavaFieldTypeEnum;
import org.amos.core.basic.enums.JavaType;
import org.amos.core.basic.utils.AmosUtils;
import org.amos.core.basic.vo.R;
import org.amos.gen.base.GeneratorConfig;
import org.amos.gen.common.GeneratorParam;
import org.amos.gen.dto.GenCodeDTO;
import org.amos.gen.dto.GenSettingDTO;
import org.amos.gen.dto.GenTableDTO;
import org.amos.gen.entity.GenDatasource;
import org.amos.gen.entity.GenTableInfo;
import org.amos.gen.entity.GenTemplate;
import org.amos.gen.service.GenDatasourceService;
import org.amos.gen.service.GenService;
import org.amos.gen.service.GenTableService;
import org.amos.gen.service.GenTemplateService;
import org.amos.gen.vo.GenColumnVo;
import org.amos.gen.vo.GenSettingVo;
import org.amos.gen.vo.GenTableVo;
import org.amos.gen.vo.GenValidVo;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 代码生成 前端控制器
 *
 * @author CodeGenerator
 * @since 2021-01-19
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/gen")
public class GenController extends BaseController {

    private final GenService genService;
    private final GenTableService genTableService;
    private final GenTemplateService genTemplateService;
    private final GenDatasourceService genDatasourceService;

    @GetMapping("/table-list")
    public R tableList(GenTableDTO dto) {
        IPage<GenTableInfo> page = genService.getGenTablePage(new Page<>(), buildWrapper(dto));
        IPage<GenTableVo> res = AmosUtils.pageCopy(page, GenTableVo.class);
        return R.ok(res);
    }

    @PostMapping("/remove")
    public R remove(@RequestBody Set<Long> ids) {
        UpdateWrapper<GenTableInfo> uw = new UpdateWrapper<>();
        uw.in(AmosUtils.toDbField(GenTableInfo::getId), ids)
                .set(AmosUtils.toDbField(GenTableInfo::getIsDeleted), SystemConstant.SYS_DELETE_FLAG_ALREADY);
        genTableService.update(uw);
        return R.ok();
    }

    @GetMapping("/column/set-info")
    public R columnList(@NotBlank(message = "缺少参数") String tableName) {
        GenSettingVo vo = new GenSettingVo();
        List<GenColumnVo> columnVos = genService.getGenColumnList(tableName);
        if (ObjectUtil.isEmpty(columnVos)) {
            columnVos = genService.getGenColDefaultList(tableName);
        }

        List<GenValidVo> validVos = genService.getGenColumnValidList(tableName);
        if (ObjectUtil.isEmpty(validVos)) {
            validVos = genService.getGenCoValidDefaultlList(tableName);
        }

        GenTableVo tableInfo = genService.getGenTableInfo(tableName);
        if (ObjectUtil.isEmpty(tableInfo)) {
            tableInfo = genService.getGenTableDefaultInfo(tableName);
        }
        vo.setColumnVos(columnVos);
        vo.setValidVos(validVos);
        vo.setTableVo(tableInfo);
        return R.ok(vo);
    }

    @GetMapping("/dict/java-type")
    public R dictJavaType() {
        List<JavaType> dictList = JavaFieldTypeEnum.dictList();
        return R.ok(dictList);
    }

    @PostMapping("/setting/save")
    @ApiOperation(value = "保存代码生成配置")
    public R create(@RequestBody @Validated GenSettingDTO dto) {
        genService.saveGenSetting(dto);
        return R.ok();
    }

    @PostMapping("/setting/refresh")
    @ApiOperation(value = "保存代码生成配置")
    public R refresh(@RequestBody @Validated GenSettingDTO dto) {
        genService.saveGenSetting(dto);
        return R.ok();
    }

    @PostMapping("/table/save")
    public R saveTableInfo(@RequestBody GenTableDTO dto) {
        GenTableInfo info = AmosUtils.copy(dto, GenTableInfo.class);
        genTableService.saveOrUpdate(info);
        return R.ok();
    }

    @PostMapping("/generator")
    @ApiOperation(value = "生成代码")
    public R generator(@RequestBody @Validated GenCodeDTO dto) {
        // 获取代码生成配置
        GenTableInfo tableInfo = genTableService.getById(dto.getId());
        String tableName = tableInfo.getTableName();
        Long groupId = tableInfo.getGroupId();
        QueryWrapper qw = new QueryWrapper();
        qw.eq(AmosUtils.toDbField(GenTemplate::getGroupId), groupId);
        List<GenTemplate> list = genTemplateService.list(qw);
        List<Long> templateIds = new ArrayList<>();
        if (CollUtil.isNotEmpty(list)) {
            templateIds = list.stream().map(GenTemplate::getId).collect(Collectors.toList());
        }

        Long datasourceConfigId = tableInfo.getDataSourceId();
        GeneratorParam generatorParam = new GeneratorParam();
        generatorParam.setAuthor(tableInfo.getAuthor());
        generatorParam.setDelPrefix(tableInfo.getTablePrefix());
        generatorParam.setDatasourceConfigId(datasourceConfigId);
        generatorParam.setTableNames(Arrays.asList(tableName));
        generatorParam.setTemplateConfigIdList(templateIds);
        generatorParam.setPackageName(tableInfo.getPackageName());
        GenDatasource genDatasource = genDatasourceService.getById(datasourceConfigId);
        GeneratorConfig generatorConfig = GeneratorConfig.build(genDatasource);
        return R.ok(genService.genCode(generatorParam, generatorConfig));
    }

    @PostMapping("/preview")
    @ApiOperation(value = "生成代码")
    public R preview(@RequestBody @Validated GenCodeDTO dto) {
        Object o = genService.previewCode(dto.getId());
        return R.ok(o);
    }

    @GetMapping("/download")
    @ApiOperation(value = "下载代码")
    public R download(GenCodeDTO dto, HttpServletResponse response) {
        genService.downloadCode(dto.getId(), response);
        return R.ok();
    }
}
